home *** CD-ROM | disk | FTP | other *** search
- /*********************************************************************\
- ** ________________________________ **
- ** A n t h o n y |________ __ __ ________| **
- ** | |o_| |o_| | **
- ** T h y s s e n __| __ __ |__ **
- ** __| __| | | |__ |__ **
- ** `` Dragon Computing ! '' __| __| | | |__ |__ **
- ** |_____| |__| |_____| **
- ** **
- \*********************************************************************/
- /* Parse the users configuration file to set up the extra workbench
- ** menus to execute various commands is various ways.
- ** (See documentation)
- */
- #undef DBUG /* don't debug this unless nessary! */
- #include "AMenu.h"
- #include "AllocStr.h" /* allocation/copy macro routines */
-
-
- /* Externs */
- extern UBYTE Color[], TColor[];
- extern UWORD FontWidth;
- extern USHORT ItemStyle;
- extern unsigned MenuGap, WBMenus;
-
- extern void Warn(char *);
- extern void StartMenu(), AddTitle(char *), AddSkip();
- extern struct ExtMenuItem *AddItem(char *, char);
- extern void AddMenu(char *, int), AddSubMenu(char *, int);
- extern void EndMenu(), EndSubMenu();
- extern BOOL FinishMenu();
-
-
- enum status { /* Parse structure levels */
- STAT_ENTRY, STAT_MENU, STAT_SUB
- };
-
- /* Multi character tokens */
- enum {
- EOF = -1, STRING,
- CONSOLE, DIRECTORY, COLOR, TCOLOR, STYLE, COMP, BOX, MENUGAP,
- MENU, SUBMENU, ENDMENU, ENDSUBMENU, COLUMNS, ITEM, TITLE, SKIP,
- RB, RUNBACK, CLI, SCR, SCRIPT, WB, STK, PRI, CON, DIR, EndToken
- }; /* Note command the modes `RB' to `WB' must be in together */
-
- /* The Arp keyword parsing string - in numeral order of tokens above */
- char *TokenTemplate =
- "CONSOLE,DIRECTORY,COLOR,TCOLOR,STYLE,COMP,BOX,MENUGAP,MENU,SUBMENU,ENDMENU,ENDSUBMENU,COLUMNS,ITEM,TITLE,SKIP,RB,RUNBACK,CLI,SCR,SCRIPT,WB,STK,PRI,CON,DIR";
-
- /* checks on the type of a commands argument */
- #define isstring(t) ( (t)<EndToken ) /* is the token any string */
- #define isnumber(t) ( isstring(t) && isdigit(*String) )
-
-
- #define S_SIZE 80
- char String[S_SIZE], NextChar; /* string token, char after string */
- BPTR Config; /* File Handle */
-
-
- /* NOTE :- The Lattice 5.04 library function `isalnum()' is
- ** incorrect in that the characters :;<=>?@ are true (is an
- ** alphanumeric character). The library functions `isdigit()'
- ** and `isalpha()' is correct, and thus used instead.
- ** The macro isalnum() in "ctype.h" works correctly, but
- ** involves the linking of the 256 byte flag buffer `_ctype[]'
- ** used by the macros.
- */
- #define isalnum(c) (isalpha(c) || isdigit(c))
-
-
- /*--------------------------------------*/
-
- static int LineNum = 0; /* Line number in config file - 0 = No Need */
-
- /* return a True on any error given to the user */
- #define ReportError(Msg) { UserReport(Msg); return TRUE; }
-
- static void
- UserReport(Msg)
- char *Msg;
- {
- if( LineNum )
- SPrintf(String, "%s : Line %ld \"%s\"", VERSION, LineNum, Msg);
- else
- SPrintf(String, "%s : \"%s\"", VERSION, Msg);
- Printf("\n%s\n", String); /* CLI Report */
- Warn(String); /* WB Report */
- }
-
-
- static char
- GetC()
- {
- char c = EOF;
- Read(Config, &c, 1);
- if( c == '\n' )
- LineNum++;
- return c;
- }
-
-
- static char
- GetToken()
- {
- char quote;
- register char tok, *p;
- register int i;
-
- retry:
- while(isspace(tok=GetC())); /* skip extra spaces */
- if( tok == '#' ) { /* comment */
- while( (tok=GetC()) != '\n' && tok != EOF ) ;
- goto retry;
- }
- quote = (tok == '"');
- if( !quote && !isalnum(tok) ) /* individual Char */
- return tok;
- if( quote ) /* remove open quote */
- tok=GetC();
-
- /* scan string token -- while !EOF, space in buffer */
- for( i=0, p=String;
- tok != EOF && i < (S_SIZE-1) && (quote ? tok!='"' : !isspace(tok));
- *p++=tok, i++, tok=GetC() );
- *p = '\0';
- NextChar = tok; /* record the next character after String */
- /* Use ARP to sort the keywords from the strings */
- tok = GetKeywordIndex( String, TokenTemplate ) + 1; /* convert token */
- DB( Printf( "%s ", String ); )
- return tok;
- }
-
-
-
- static BOOL
- ParseConfig()
- {
- register char t, Statement;
- struct ExtMenuItem *EItem;
- char Name[80], CommandChar, *p;
- BOOL OptionLoop;
- enum status status = STAT_ENTRY;
- int Columns;
-
- LineNum = 1; /* report config line number on errors */
- DB( Printf("\n"); )
- while ( (Statement=GetToken()) != EOF ) {
- switch( Statement ) {
- case CONSOLE:
- if( !isstring(GetToken()) )
- ReportError("Bad CONSOLE Argument");
- if( M->Console ) FreeStr(M->Console);
- M->Console = AllocStr(String);
- break;
- case DIRECTORY:
- if( !isstring(GetToken()) )
- ReportError("Bad DIRECTORY Argument");
- if( M->Directory ) FreeStr(M->Directory);
- M->Directory = AllocStr(String);
- break;
-
- case COLOR:
- if( !isnumber(GetToken()) )
- ReportError("Bad COLOR Argument 1");
- Color[0] = (UWORD)Atol(String);
- if( !isnumber(GetToken()) )
- ReportError("Bad COLOR Argument 2");
- Color[1] = (UWORD)Atol(String);
- break;
-
- case TCOLOR:
- if( !isnumber(GetToken()) )
- ReportError("Bad TCOLOR Argument 1");
- TColor[0] = (UWORD)Atol(String);
- if( !isnumber(GetToken()) )
- ReportError("Bad TCOLOR Argument 2");
- TColor[1] = (UWORD)Atol(String);
- break;
-
- case STYLE:
- switch( GetToken() ) {
- case COMP: ItemStyle = HIGHCOMP; break;
- case BOX: ItemStyle = HIGHBOX; break;
- default:
- ReportError("Bad STYLE Argument");
- }
- break;
-
- case MENUGAP:
- if( !isnumber(GetToken()) )
- ReportError("Bad MENUGAP Argument");
- MenuGap = (UWORD)Atol(String);
- if( MenuGap<1 || MenuGap>50 )
- ReportError("MENUGAP out of range");
- MenuGap *= FontWidth;
- break;
-
- case MENU:
- switch( status ) { /* fall through switch */
- case STAT_SUB:
- EndSubMenu();
- case STAT_MENU:
- EndMenu();
- }
- status = STAT_MENU;
- Columns = 1;
- if( (t=GetToken() == COLUMNS ) ) {
- if( !isnumber(t=GetToken()) )
- ReportError("Bad COLUMNS Argument");
- Columns = Atol(String);
- t=GetToken();
- }
- if( !isstring(t) )
- ReportError("Missing Menu Name");
- AddMenu( String, Columns );
- break;
-
- case SUBMENU:
- switch( status ) {
- case STAT_ENTRY:
- ReportError("Menu Statement expected");
- case STAT_SUB:
- EndSubMenu();
- }
- status = STAT_SUB;
- Columns = 1;
- if( (t=GetToken() == COLUMNS ) ) {
- if( !isnumber(t=GetToken()) )
- ReportError("Bad COLUMNS Argument");
- Columns = Atol(String);
- t=GetToken();
- }
- if( !isstring(t) )
- ReportError("Missing SubMenu Name");
- AddSubMenu( String, Columns );
- break;
-
- case ENDMENU:
- switch( status ) {
- case STAT_ENTRY:
- ReportError("Menu Statment expected");
- case STAT_SUB:
- EndSubMenu();
- }
- EndMenu();
- status = STAT_ENTRY;
- break;
-
- case ENDSUBMENU:
- if( status != STAT_SUB ) {
- ReportError("SubMenu Statment expected");
- }
- EndSubMenu();
- status = STAT_MENU;
- break;
-
-
- case SKIP: /* these are pretty simalar */
- case TITLE:
- case ITEM:
- switch( status ) {
- case STAT_ENTRY:
- ReportError("Menu Statement expected");
- }
- if( Statement == SKIP ) { /* if Skip finish up */
- AddSkip();
- break;
- }
- if( !isstring(GetToken()) )
- ReportError("Missing Item/Title Name");
- strcpy(Name, String);
-
- if( Statement == TITLE ) { /* if Title finish up */
- AddTitle(Name);
- break;
- }
- CommandChar = '\0';
- if( (t=GetToken()) == '<' ) { /* command char */
- /* the next line works with 1.3
- * however, WB 2.0 has its own CTRL characters
- * so simply get a token
- CommandChar = GetC();
- */
- (void)GetC(); /* WB 2.0 "new" code */
- if( GetToken() != '>' )
- ReportError("Missing closing '>'");
- t = GetToken();
- }
- if( t != '|' )
- ReportError("Missing '|' separator");
- DB( Printf("| "); )
- EItem = AddItem(Name, CommandChar);
- if( (t=GetToken()) < RB || t > WB )
- ReportError("Missing Execution Mode");
- EItem->Mode = Toupper(String[0]); /* R,C,S,W as appropiate */
- EItem->Stack = DEF_STACK; /* Default Stack Size */
- EItem->Pri = 0; /* Default Prioity */
- for( OptionLoop=TRUE; OptionLoop; ) {
- switch( t=GetToken() ) {
- case STK: /* Stack -- All modes */
- if( !isnumber(t=GetToken()) )
- ReportError("Bad STK Argument");
- EItem->Stack = (ULONG)Atol(String);
- if( EItem->Stack < 500 || EItem->Stack > 1000000 )
- ReportError("Bad STACK Size given");
- break;
- case PRI: /* Prioity -- All modes */
- { BOOL neg;
- if( neg = ( (t=GetToken()) == '-') ) t=GetToken();
- if( !isnumber(t) )
- ReportError("Bad PRI Argument");
- EItem->Pri = (BYTE)Atol(String);
- if(neg) EItem->Pri = -EItem->Pri;
- }
- break;
- case CON: /* Console -- CLI & SCRIPT only */
- if( EItem->Mode != 'C' && EItem->Mode != 'S' )
- ReportError("`CON' -- CLI or SCRIPT modes only");
- if( !isstring(t=GetToken()) )
- ReportError("Bad CON Argument");
- if( EItem->Console ) FreeStr(M->Console);
- EItem->Console = AllocStr(String);
- break;
- case DIR: /* Current Directory -- not WB */
- if( EItem->Mode == 'W' )
- ReportError("`DIR' -- not in WB mode");
- if( !isstring(t=GetToken()) )
- ReportError("Bad DIR Argument");
- if( EItem->Directory ) FreeStr(M->Directory);
- EItem->Directory = AllocStr(String);
- break;
- default:
- OptionLoop = FALSE;
- break;
- } /* switch */
- } /* option loop */
-
- /* command */
- if( !isstring(t) )
- ReportError("Bad Command Given");
- EItem->Cmd = AllocStr(String);
-
- /* read arguments */
- t = NextChar; /* char following command string*/
- while( t != '\n' && t != EOF && isspace(t) )
- t=GetC(); /* skip space */
- p = String;
- while( t != '\n' && t != EOF ) {
- *p++ = t; /* read in rest of line */
- t = GetC(t);
- }
- *p++ = '\n'; /* make it a proper command line */
- *p = '\0';
- if( EItem->Mode != 'W' && EItem->Mode != 'S' ) /* ignore args? */
- EItem->Args = AllocStr(String);
- break; /* end of ITEM statement */
-
- default:
- ReportError("Keyword Expected");
- }
-
- DB( Printf("-END\n"); )
- } /* While Token */
-
- switch( status ) {
- case STAT_SUB:
- EndSubMenu();
- case STAT_MENU:
- EndMenu();
- }
- LineNum = 0; /* finished config file - no more syntax errors */
- return FALSE;
- }
-
-
- BOOL
- ParseMenus()
- /* Open and Read the Config File -- return FALSE if no error */
- {
- BOOL Error;
-
- if( M->Directory ) FreeStr(M->Directory);
- M->Directory = AllocStr(DEF_DIRECTORY);
- if( M->Console ) FreeStr(M->Console);
- M->Console = AllocStr(DEF_CONSOLE);
-
- StartMenu();
- /*
- * WB 1.3 had only 3 menus in the work bench
- if( WBMenus != 3 )
- */
- if( WBMenus != 4 )
- ReportError("Unusual Workbench Menus Found!");
-
- Config = ArpOpen(AMENU_CONFIG, MODE_OLDFILE);
- if( !Config ) {
- Config = ArpOpen(AMENU_CONFIG2, MODE_OLDFILE); /* closed by Arp */
- if( !Config )
- ReportError("Can't find file");
- }
-
- Error = ParseConfig();
-
- if( !Error && FinishMenu() ) {
- SPrintf(String, "%s : \"%s\"", VERSION,
- "Warning: Menu Overflows WorkBench Screen!");
- Warn(String); /* Warning - don't abort */
- }
-
- return Error;
- }
-
-